/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */
package net.sk.mina.imagine.client;

import net.bat.util.Cfg;
import net.sk.jni.Plate;
import net.sk.mina.imagine.FrameHeader;
import net.sk.mina.imagine.ImageRequest;
import net.sk.mina.imagine.ImageResponse;
import net.sk.mina.imagine.ImgServlet;
import net.sk.mina.imagine.codec.ImageCodecFactory;
import net.sk.pt.IKeeper;
import net.sk.pt.State;
import net.sk.web.Keeper;
import net.sk.web.Provider;

import org.apache.mina.core.RuntimeIoException;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import dao.hb.ODevice;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.HashMap;

import javax.imageio.ImageIO;

/**
 * client for the {@link ImageServer}
 *
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public class ImageClient extends IoHandlerAdapter {
	static final boolean bjni = false;
	//本地调用对象
	Plate plt = null;
	//心跳帧回送
	static public final int ack= 0x55AA55AA;
	
    public static final int CONNECT_TIMEOUT = 3000;
    public static final int CONNECT_SPAN = 10000;
    public static final String IMG_FMT = "png";

    private String host;
    private int port;
    private SocketConnector connector;
    private IoSession session;
    private ImageListener imageListener;
    private ODevice od=null;
    public static String PR_CAMERA="PR_CAMERA_";
    public static String CN_CAMERA="CN_CAMERA";
    
	static String[] RS = new String[]{
		"[[\"京A778899\",\"蓝\",\"类型1\",10,10,30,30,0.99,10]]",
		"[[\"京A111111\",\"黑\",\"类型2\",10,10,30,30,0.99,10],[\"川A9876543\",\"蓝\",\"类型5\",80,80,120,100,0.95,33]]",
		"[[\"川B141414\",\"黄\",\"类型3\",80,80,120,100,0.95,33]]"
	};
	int pos_rs=0;

	Provider pr;

    public ImageClient(ODevice od, int port, ImageListener imageListener) {
    	this(od.getIpAddr(),port,imageListener);
    	this.od = od;
        pr = new Provider(new Keeper(),PR_CAMERA+od.getId());
        Cfg.getSC().addProvider(pr);
    }

    public ImageClient(String host, int port, ImageListener imageListener) {
        this.host = host;
        this.port = port;
        this.imageListener = imageListener;
        connector = new NioSocketConnector();
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ImageCodecFactory(true)));
        connector.setHandler(this);
    }
    
    public Plate getPlt(){
    	if(plt==null){
    		plt = new Plate("TH_PlateResult");
    		plt.InitPlate();
    	}
    	return plt;
    }

    public boolean isConnected() {
        return (session != null && session.isConnected());
    }

    public void connect() {
        ConnectFuture connectFuture = connector.connect(new InetSocketAddress(host, port));
        connectFuture.awaitUninterruptibly(CONNECT_TIMEOUT);
        try {
            session = connectFuture.getSession();
        }
        catch (RuntimeIoException e) {
            imageListener.onException(e);
            reconnect();
        }
    }

    public void reconnect(){
        try {
			Thread.sleep(CONNECT_SPAN);
			connect();
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}    	
    }
    public void disconnect() {
        if (session != null) {
            session.close(true).awaitUninterruptibly(CONNECT_TIMEOUT);
            session = null;
        }
    }

    public void sessionOpened(IoSession session) throws Exception {
        imageListener.sessionOpened();
    }

    public void sessionClosed(IoSession session) throws Exception {
        imageListener.sessionClosed();
    }

    public void sendRequest(ImageRequest imageRequest) {
        if (session == null) {
            //noinspection ThrowableInstanceNeverThrown
            imageListener.onException(new Throwable("not connected"));
        } else {
            session.write(imageRequest);
        }
    }

    public void messageReceived(IoSession session, Object message) throws Exception {
        ImageResponse response = (ImageResponse) message;
        if(response.getFh().getFrame_type()==FrameHeader.FRAME_TYPE_HEART){
        	//收到心跳帧
            IoBuffer buffer = IoBuffer.allocate(4, false);
            buffer.putInt(ack);
            buffer.flip();
        	session.write(buffer);
        }else{
        	//收到图像帧
	        onImage(response.getFh(), response.getImage1());
	        imageListener.onImages(response.getFh(), response.getImage1());
        }
    }
    private String parseResult(String fn){
    	//TODO jni调用号牌识别
    	if(bjni){
    		return getPlt().GetPlateResult(fn);
    	}else{
    		return randResult();
    	}
    }
    private String randResult(){
    	pos_rs++;
    	if(pos_rs==RS.length){
    		pos_rs=0;
    	}
    	return RS[pos_rs];
    }
    private void onImage(FrameHeader fh,BufferedImage image1){
		Date dt = new Date();
		String fpath = Cfg.getInitParameter("work_path")+od.getId();
		File fp = new File(fpath);
		if(fp.exists()||!fp.isDirectory()){
			fp.mkdir();
		}
		fpath+=File.separator;
		
		long tm = dt.getTime();
		String fn1 =fpath+"f1-"+tm+"."+IMG_FMT;
/*		try {
			ImageIO.write(image1, IMG_FMT, new File(fn1));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
*/		
		ImgServlet.setImg(od.getId(),image1);
		State s = new State();
		s.setAction(State.ACTION_PUT);
		s.setCn(CN_CAMERA);
		HashMap its = new HashMap();
		its.put("fn", fn1);
		its.put("tm", tm);
		its.put("result", parseResult(fn1));
		s.setKey(od.getId());
		s.setItems(its);
		pr.send(s);
		//TODO send State for websocket
    }

    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        imageListener.onException(cause);
        disconnect();
        reconnect();
    }

}
